<template>
  <!-- 页面容器组件 -->
  <PageContainer>
    <Header
      title="智能体"
      v-model:model-value="headerHeight"
      :default-slot-content-height="160"
      :data="botInfo"
    >
      <view class="header-box">
        <TipBox v-if="!userStore.userInfo?.isOpenBot">
          <template #title>您有一个专属智能助手待激活</template>
          <template #btn>
            <text class="hb-text-sm hb-text-[#2878FF]" @click="handleClick">立即激活</text>
          </template>
        </TipBox>
        <AiInfo v-if="botInfo" :bot-info="botInfo" :uuid="uuid" />
      </view>
    </Header>
    <view
      :style="{
        backgroundPosition: 'center',
        backgroundRepeat: 'no-repeat',
        backgroundSize: 'cover',
        ...(botInfo?.backImage
          ? {
              backgroundImage: `url(${botInfo?.backImage})`,
            }
          : {
              background:
                'linear-gradient(156deg, rgba(255, 242, 142, 0.20) 0%, rgba(255, 234, 201, 0.00) 61.79%), linear-gradient(180deg, #DFEBFF 0%, rgba(227, 238, 255, 0.00) 100%), #FFF',
            }),
      }"
    >
      <scroll-view
        class="scroll-view-container"
        :scroll-y="true"
        :scroll-anchoring="true"
        :scroll-top="scrollTop"
        :scroll-with-animation="true"
        :enable-passive="true"
        @scrolltolower="scrolltolower"
        :style="{
          height: `${windowHeight - (windowHeaderHeight || headerHeight)}px`,
        }"
        style="transform: rotate(180deg)"
      >
        <!-- 顶部加载指示器 -->

        <view
          class="hb-p-3 hb-relative hb-flex hb-flex-col hb-justify-end"
          :style="{ minHeight: '100%' }"
        >
          <ChatSkeleton
            v-if="!initSuccess && botInfo"
            :visible="hasMore"
            :scroll-height="windowHeight - (windowHeaderHeight || headerHeight)"
          />

          <view>
            <view
              class="placeholder"
              :style="{
                height: `${footerHeight}px`,
              }"
            ></view>
            <!-- 显示消息列表 -->
            <template v-for="(item, index) in messageList" :key="index">
              <view style="transform: rotate(180deg)">
                <!-- <view :id="`page${item.id}`"></view> -->
                <ReplyMessageBox
                  v-if="item.type === MessageType.ANSWER"
                  :data="item"
                  :index="index"
                  :is-last="index === 0"
                  @resend="handleResend"
                  @send="handleMessageSend"
                ></ReplyMessageBox>
              </view>
              <view style="transform: rotate(180deg)">
                <SendMessageBox v-if="item.type === MessageType.QUESTION" :message="item.content">
                  <template #default>
                    <MessageTool
                      :refreshable="false"
                      :content="item.content"
                      justify="flex-end"
                    ></MessageTool>
                  </template>
                </SendMessageBox>
              </view>
            </template>
            <view id="scroll-bottom"></view>
          </view>
        </view>
      </scroll-view>

      <ChatInput
        :show-chat-source="
          userStore.customerServiceUuid !== uuid &&
          userStore.userInfo?.aiUserAccountBotVo?.uuid === uuid
        "
        :circle-uuid="circleUuid"
        :circle-name="circleName"
        :chat-source="chatSource"
        :last-message="lastMessage"
        :input-content="inputContent"
        :auto-focus="false"
        @source-change="setChatSource"
        @update-footer-height="updateFooterHeight"
        @update-input-content="setInputContent"
        @send="handleMessageSend"
        @cancel="cancelCurrentQuery"
      />
    </view>
    <Guide v-if="getGuideVisible" :steps-number="1" :type="GuideType.CHAT" />
  </PageContainer>
</template>

<script lang="ts" setup>
  // 获取 chatStore 实例
  import { nextTick, ref } from 'vue';
  import ReplyMessageBox from './components/ReplyMessageBox.vue';
  import SendMessageBox from './components/SendMessageBox.vue';
  import AiInfo from './components/AiInfo.vue';
  import ChatInput from '@/components/ChatInput/index.vue';
  import MessageTool from './components/MessageTool.vue';
  import TipBox from '@/components/TipBox/index.vue';
  import ChatSkeleton from './components/ChatSkeleton.vue';
  import { ChatSource, MessageType } from '@/enums/MessageEnum';
  import { useUserStore } from '@/store/modules/user';
  import { BotInfo, MessageRecord } from '@/api/aiChatPage/types';
  import {
    addAnswer,
    chatCancel,
    conversationCreate,
    conversationMessageList,
    getBotById,
    streamChat,
  } from '@/api/aiChatPage';
  import { AbortablePromise } from '@/utils/http/types';
  import debounce from 'lodash-es/debounce';
  import { GuideType } from '@/store/modules/guide';
  import { CacheEnum } from '@/enums/CacheEnum';

  const userStore = useUserStore();
  const getGuideVisible = computed(() => {
    const cacheVisible = uni.getStorageSync(CacheEnum.CHAT_GUIDE_VISIBLE);
    if (userStore.customerServiceUuid !== uuid.value && botInfo.value && !cacheVisible) {
      uni.setStorageSync(CacheEnum.CHAT_GUIDE_VISIBLE, true);
      return true;
    }
    return false;
  });

  const messageList = ref<Array<MessageRecord & { pageNum?: number }>>([]);
  const conversationId = ref('');
  const uuid = ref(''); // 机器人ID
  const inputContent = ref('');
  const currentStream = ref<null | AbortablePromise<any>>(null);
  const current = ref(0); // 当前页码
  const size = ref(20); // 每页数量
  const hasMore = ref(true); // 是否有更多历史记录
  const isLoadingMore = ref(false);
  const circleUuid = ref('');
  const circleName = ref('');
  const chatSource = ref(ChatSource.PRIVATE);

  // 全局共享配置
  const loadingText = '正在思考...';
  const headerHeight = ref(0);
  const footerHeight = ref(uni.upx2px(136));
  const windowHeight = uni.getSystemInfoSync().windowHeight;

  const scrollTop = ref(0);

  // 计算属性
  const lastMessage = computed(() => {
    const items = messageList.value.filter((item) => item.type === MessageType.ANSWER);
    return items.length ? items[0] : ({} as MessageRecord);
  });

  const scrollHeight = computed(() => {
    return windowHeight - headerHeight.value - footerHeight.value;
  });

  // 初始化成功
  const initSuccess = ref(false);

  customOnload<'AiChatPage'>(async (options) => {
    // 设置圈子信息
    setCircleInfo(
      options.circleUuid || '',
      options.circleName || '',
      options.chatSource || ChatSource.PRIVATE,
    );
    // 设置机器人ID
    uuid.value = options.uuid || userStore.userInfo?.aiUserAccountBotVo?.uuid || '';
    // 查询机器人信息
    queryBotById();
    // 初始化聊天
    await initChat();
    queryHeaderHeight();
    setTimeout(() => {
      initSuccess.value = true;
    }, 500);
  });
  const windowHeaderHeight = ref(0);
  const queryHeaderHeight = async () => {
    console.log(headerHeight.value);
    uni
      .createSelectorQuery()
      .select('.header-box')
      .boundingClientRect((res: any) => {
        if (res && uni.getSystemInfoSync().platform === 'windows') {
          windowHeaderHeight.value = res.height;
        }
      })
      .exec();
  };

  const botInfo = ref<BotInfo>();

  const queryBotById = async () => {
    const res = await getBotById(uuid.value);
    botInfo.value = res;
  };

  const scrolltolower = async () => {
    await loadMoreMessages();
  };

  const handleClick = () => {
    navigateTo({
      name: 'createAi',
    });
  };

  // 创建消息
  const createMessage = (
    type: MessageType,
    content: string,
    options: Partial<MessageRecord> = {},
  ): MessageRecord => {
    return {
      type,
      content,
      loading: false,
      typing: false,
      ...options,
    } as MessageRecord;
  };

  // 创建并添加消息
  const createAndAddMessage = (type: MessageType, content: string, options = {}) => {
    const message = createMessage(type, content, options);
    messageList.value.unshift(message);
    return message;
  };

  // 设置最后一条消息
  const setLastMessage = (value: MessageRecord) => {
    const lastMsg = messageList.value[0];
    if (!lastMsg) return;

    lastMsg.typing = value.typing;
    lastMsg.loading = value.loading;
    if (lastMsg.content.includes(loadingText)) {
      lastMsg.content = lastMsg.content.replace(loadingText, '') + value.content;
    } else {
      lastMsg.content = lastMsg.content + value.content;
    }
  };

  // const handleMouseWheel = debounce((event: any) => {
  //   console.log('event', event.detail);

  //   if (event.detail.deltaY > 0) {
  //     scrollTop.value = scrollTop.value - 50;
  //   } else {
  //     scrollTop.value = scrollTop.value + 50;
  //   }
  // }, 10);

  // 发送消息
  const handleMessageSend = debounce(async (content: string) => {
    // 重置输入框
    inputContent.value = '';
    const trimmedContent = content.trim();
    if (!trimmedContent) return;

    try {
      createAndAddMessage(MessageType.QUESTION, trimmedContent);
      createAndAddMessage(MessageType.ANSWER, loadingText, {
        typing: true,
        loading: true,
      });

      setTimeout(() => {
        scrollTop.value = 0;
      }, 100);

      const stream = streamChat({
        conversationId: conversationId.value,
        uuid: uuid.value,
        contentType: 'text',
        content: trimmedContent,
        chatSource: chatSource.value as ChatSource,
        circleUuid: circleUuid.value,
      });

      // 拼接流式数据
      stream.onChunk((chunk) => {
        setLastMessage({
          content: chunk,
          typing: true,
          loading: false,
        });
      });

      // 流式数据结束
      stream.onComplete(() => {
        nextTick(() => {
          setLastMessage({
            content: '',
            typing: false,
            loading: false,
          });
          currentStream.value = null;
          if (lastMessage.value.content) {
            addAnswer({
              conversationId: conversationId.value,
              content: lastMessage.value.content,
              uuid: uuid.value,
              contentType: 'text',
            });
          }
        });
      });

      stream.onError((error) => {
        if (error.errMsg === 'request:fail abort') {
          return;
        }
        setLastMessage({
          content: '发送错误',
          typing: false,
          loading: false,
        });
      });

      // 取消流式请求
      stream.onCancel(async () => {
        // 取消服务端的请求
        await chatCancel({
          conversationId: conversationId.value,
        });
        setLastMessage({
          content: '取消回复',
          typing: false,
          loading: false,
        });
      });

      // 启动流并保存引用
      currentStream.value = stream.start();
    } catch (error: any) {
      setLastMessage({
        content: '抱歉，处理您的消息时出现了问题',
        typing: false,
        loading: false,
      });
    }
  }, 50);

  // 重发消息
  const handleResend = debounce(async () => {
    const lastQuestion = messageList.value.find((item) => item.type === MessageType.QUESTION);
    if (lastQuestion) {
      handleMessageSend(lastQuestion.content);
    }
  }, 50);

  // 取消当前查询
  const cancelCurrentQuery = async () => {
    if (currentStream.value) {
      currentStream.value.abort();
      currentStream.value = null;
    }
  };

  // 初始化聊天
  const initChat = async () => {
    try {
      // 创建会话
      const createRes = await conversationCreate(uuid.value);
      conversationId.value = createRes.id;
      // 查询最新消息
      await loadMessages();
    } catch (error) {
      uni.showToast({
        title: '初始化对话失败',
        icon: 'none',
      });
    }
  };

  // 设置输入内容
  const setInputContent = (content: string) => {
    inputContent.value = content;
  };

  // 更新底部高度
  const updateFooterHeight = (height: number) => {
    footerHeight.value = height;
  };

  // 加载消息
  const loadMessages = async () => {
    isLoadingMore.value = true;
    try {
      const requestPage = current.value + 1;
      const res = await conversationMessageList({
        conversationId: conversationId.value,
        current: requestPage,
        size: size.value,
      });
      hasMore.value = requestPage * size.value <= res.total;

      if (requestPage === 1) {
        messageList.value = res.records;
      } else {
        messageList.value.push(...res.records);
      }

      current.value = requestPage;
    } catch (error) {
      uni.showToast({
        title: '加载消息失败',
        icon: 'none',
      });
    } finally {
      isLoadingMore.value = false;
    }
  };

  // 加载更多消息
  const loadMoreMessages = async () => {
    if (hasMore.value && !isLoadingMore.value) {
      await loadMessages();
    }
  };

  // 设置聊天来源
  const setChatSource = (source: ChatSource) => {
    chatSource.value = source;
  };

  // 设置圈子信息
  const setCircleInfo = (uuid: string, name: string, source: ChatSource) => {
    circleUuid.value = uuid;
    circleName.value = name;
    chatSource.value = source;
  };
</script>

<style lang="scss" scoped></style>
